﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using md.imi.membranes.objects.Gui;

namespace md.imi.membranes.objects.membranes
{
    /// <summary>
    ///     Represents a tree of membranes hierarchy
    /// </summary>
    [Serializable]
    public class MembranesTree : Membrane, IDisposable
    {
        private Membrane membrane;

        public MembranesTree () : base()
        {
             Membranes = new List<MembranesTree>();
        }

        /// <summary>
        ///     Copy constructor. Copies passed membrane content  to ouwn
        /// </summary>
        /// <param name="membrane"></param>
        public MembranesTree(Membrane membrane) : base(membrane)
        {
            var mt = membrane as MembranesTree;
            if (mt != null && (mt.Membranes.Count > 0))
            {
                this.Membranes = new List<MembranesTree>();
                // copy one level membranes. Other membrane's copy-constructor will take
                // care to copy all others
                foreach (var mt1 in mt.Membranes)
                {
                    this.Membranes.Add(new MembranesTree(mt1));
                }
            }
        }

        /// <summary>
        ///     Copy constructor
        /// </summary>
        /// <param name="membrane"></param>
        public MembranesTree(MembranesTree membrane)
            : base(membrane)
        {
            // perform additional copy-constructor ations if required
            this.Membranes = new List<MembranesTree>();
            // copy one level membranes. Other membrane's copy-constructor will take
            // care to copy all others
            foreach (var mt1 in membrane.Membranes)
            {
                this.Membranes.Add(new MembranesTree(mt1));
            }

        }

        /// <summary>
        /// 
        /// </summary>
        //[XmlArray("MembranesTree"), XmlArrayItem("MembranesTree", typeof(MembranesTree))]
        public List<MembranesTree> Membranes { get; set; }

        /// <summary>
        ///     Iterate trough list of child membranes, and dispose them recursively
        /// </summary>
        /// <param name="membranes"></param>
        public void Dispose (List<MembranesTree> membranes)
        {
            if (membranes == null ) return;
            foreach( var item in membranes)
            {
                item.Dispose();
            }
        }
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public new void Dispose()
        {
            base.Dispose();
            this.Dispose(Membranes);
        }

        public String DumpMultiset()
        {
            var multisetString = new StringBuilder();

            if (Multiset == null || Multiset.Count == 0)
            {
                return multisetString.ToString();
            }

            foreach (var m in Multiset)
            {
                if (multisetString.Length > 0)
                    multisetString.Append(",");

                multisetString.Append(m.ToString());
            }

            return multisetString.ToString();
        }

        public void ReplaceMembraneContentById(MembranesTree modifiedMembrane)
        {
            
            if (modifiedMembrane == null)
            {
                return;
            }


            MembranesTree foundMembrane = SearchMembraneById(this.Membranes, modifiedMembrane.Id);
            if (foundMembrane == null)
            {
                return; // membrane not found
            }

            // perform replacement
            foundMembrane.Multiset = modifiedMembrane.Multiset;
            foundMembrane.Label = modifiedMembrane.Label;
            foundMembrane.Charge = modifiedMembrane.Charge;
            foundMembrane.GuiInfo = new GuiInfo(modifiedMembrane.GuiInfo);
            foundMembrane.Multiplicity = modifiedMembrane.Multiplicity;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="membranes"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static MembranesTree SearchMembraneById(List<MembranesTree> membranes, Guid id)
        {
            if (membranes == null || membranes.Count == 0)
            {
                return null;
            }

            foreach (var m in membranes)
            {
                if (m.Id.Equals(id))
                {
                    return m;
                }

                var foundMembrane = SearchMembraneById(m.Membranes, id);
                if (foundMembrane != null)
                {
                    return foundMembrane;
                }
            }

            return null;
        }

        /// <summary>
        /// Check ifcurrent membrane is not an environment membrane
        /// </summary>
        /// <returns></returns>
        public bool IsEnvironment()
        {
            return String.IsNullOrEmpty(Label) == false && Label.Equals(("Environment"));
        }
    }
}
